home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 10
/
FM Towns Free Software Collection 10.iso
/
ms_dos
/
tool
/
mls
/
mls.for
< prev
next >
Wrap
Text File
|
1995-02-17
|
20KB
|
642 lines
***********************************************************************
******************** ***************************
************** MLS Ver.1.00 **********************
******************** ***************************
***********************************************************************
C
PROGRAM MLS
PARAMETER (MAX=100)
DIMENSION A(MAX,MAX),B(MAX,MAX),C(MAX,MAX),R(MAX,MAX),W(MAX,MAX)
DIMENSION D(MAX,MAX),EN(MAX),Z(MAX),XX(MAX),XS(MAX),V(MAX)
INTEGER X(MAX),JCH(MAX)
CHARACTER QT*1,FILE*25
1 ID=0
CALL START(MENU)
IF(MENU.EQ.5) THEN
CALL MAKE2(B,XX,K,N,D,JCH,MAX,MENU)
CALL COPYMTX(B,A,N,K,MAX)
CALL COPYMTX(XX,XS,N,1,MAX)
GOTO 46
111 END IF
IF(MENU.NE.2) THEN
CALL MAKE(A,W,XS,M,N,MENU,MAX,ICH)
ELSE
18 WRITE(6,104)'DATA 数を入力して下さい'
READ(5,*,ERR=18) M
IF(M.LE.0) THEN
WRITE(6,*) ' 入力しなおしてください!'
GOTO 18
24 END IF
WRITE(6,*)'DATA の入力方法を指定してください'
73 WRITE(6,*)'1:直接入力 2:DATA FILEによる入力'
READ(5,*,ERR=73) IDATA
IF(IDATA.LE.0.OR.IDATA.GE.3) GOTO 73
74 IF(IDATA.EQ.2) THEN
WRITE(6,*)'FILE の名前を入力してください'
READ(5,301) FILE
OPEN(1,FILE=FILE)
ELSE
WRITE(6,*)' DATA を X,Y の順に入力して下さい'
END IF
DO 4 I=1,M
IF(IDATA.EQ.1) THEN
READ(5,*) XX(I),EN(I)
ELSE
READ(1,*) XX(I),EN(I)
IF(I.EQ.M) CLOSE(1)
END IF
4 CONTINUE
WRITE(6,105)'反復数、傾きの順に出力します'
CALL BEW(XX,EN,XS,V,Z,M)
GOTO 68
5 CONTINUE
END IF
IDA=0
K=0
IF(ICH.EQ.1) THEN
K=M-1
END IF
11 K=K+1
12 CALL PRDMTX(W,A,B,N,N,K,MAX)
CALL PRDMTX(W,XS,XX,N,N,1,MAX)
46 CALL QR(B,R,X,EN,N,K,MAX,ID)
IF(ID.EQ.1) GOTO 7
25 CALL TRANSMTX(B,C,X,N,K,MAX)
CALL TENMTX(C,B,N,K,MAX)
CALL PRDMTX(B,XX,Z,K,N,1,MAX)
CALL BACK(R,XX,Z,K,MAX)
IF(MENU.EQ.1.AND.K.EQ.M) GOTO 6
IF(IDA.EQ.1.OR.ICH.EQ.1) GOTO 6
IF(MENU.EQ.5.OR.MENU.EQ.6) GOTO 6
CALL PRDMTX(W,A,C,N,N,K,MAX)
CALL TRANS(XX,V,X,K)
CALL COPYMTX(V,XX,K,1,MAX)
CALL PRDMTX(W,XS,V,N,N,1,MAX)
CALL COPYMTX(V,XS,N,1,MAX)
CALL PRDMTX(C,XX,V,N,K,1,MAX)
28 CALL AIC(V,XS,K,N,AI)
IF(MENU.NE.1) THEN
IF(K.EQ.1) THEN
IAI=K
SAI=AI
ELSE IF(AI+1.0.LT.SAI) THEN
IAI=K
SAI=AI
END IF
END IF
IF(K.NE.M) GOTO 11
17 K=IAI
IDA=1
IF(MENU.EQ.3) THEN
L=K
ELSE IF(MENU.EQ.4) THEN
L=K-1
END IF
IF(ICH.EQ.2) THEN
WRITE(6,201) L
END IF
GOTO 12
6 CALL SOLVE(XX,X,K,MENU)
IF(MENU.EQ.5) THEN
13 CALL TRANS(XX,V,X,K)
CALL COPYMTX(V,XX,K,1,MAX)
CALL PRDMTX(A,XX,V,N,K,1,MAX)
CALL AIC5(D,XS,XX,JCH,K,N,MAX,AI)
END IF
68 WRITE(6,106)'以上の結果になりました'
7 WRITE(6,103)'再び実行しますか? ( Y or N )'
READ(5,108) QT
IF(QT.EQ.'N'.OR.QT.EQ.'n') THEN
CALL MES
STOP
ELSE IF(QT.EQ.'Y'.OR.QT.EQ.'y') THEN
GOTO 1
8 ELSE
GOTO 7
9 END IF
STOP
103 FORMAT(2X,A34)
104 FORMAT(/,2X,A27)
105 FORMAT(/,2X,A32)
106 FORMAT(/,5X,A35)
108 FORMAT(A1)
201 FORMAT( /,10X,I3,' 次式が最も良い近似です')
301 FORMAT(A25)
END
************************************************************************
* SUBROUTINE TO OUTPUT THE MESSAGES *
************************************************************************
SUBROUTINE MES
WRITE(6,*)'THANK YOU FOR USING MLS! SEE YOU AGAIN!!'
WRITE(6,*)'MERCI BEAUCOUP!! AU REVOIR!!'
WRITE(6,*)'DANKE!! AUF WIEDERSEHEN!!'
WRITE(6,*)'謝謝!! 再見!!'
WRITE(6,*)'GRAZIE!! ARRIVEDERCI!!'
WRITE(6,*)'GRACIAS!! HASTA LUEGO!!'
WRITE(6,*)'OBRIGADO!! ATE LOGO!!'
WRITE(6,*)'СПАСИБО!!'
WRITE(6,*)'БАЯРЛАЛАА!!'
RETURN
END
************************************************************************
* SUBROUTINE TO CHOOSE THE PROGRAM *
************************************************************************
SUBROUTINE START(MENU)
CHARACTER QT*1
WRITE(6,101) '最小二乗法プログラム'
19 WRITE(6,102)'近似する方法を選んで下さい'
WRITE(6,*)
*'1:多項式近似 2:比例式近似 3:連立方程式 4:重回帰モデル'
READ(5,*,ERR=19) MENU
IF(MENU.LE.0.OR.MENU.GE.5) GOTO 19
IF(MENU.EQ.4) THEN
MENU=5
RETURN
END IF
MENU=4-MENU
IF(MENU.EQ.3) THEN
2 WRITE(6,103)'定数項は入れますか?( Y or N )'
READ(5,108) QT
IF(QT.EQ.'Y'.OR.QT.EQ.'y') THEN
MENU=MENU+1
ELSE IF(QT.NE.'N'.AND.QT.NE.'n') THEN
GOTO 2
3 END IF
END IF
RETURN
101 FORMAT(/,5X,A46)
102 FORMAT(/,2X,A30)
103 FORMAT(2X,A34)
108 FORMAT(A1)
END
***********************************************************************
* SUBROUTINE TO IMPUT THE DATA AND TO MAKE THE MATRIX *
***********************************************************************
SUBROUTINE MAKE(A,W,X,M,N,MENU,MAX,ICH)
DIMENSION A(MAX,MAX),X(1),W(MAX,MAX)
CHARACTER FILE*25
IF(MENU.EQ.1) THEN
11 WRITE(6,*)'パラメーターの数を入力して下さい'
READ(5,*,ERR=11) M
IF(M.LE.0) THEN
WRITE(6,*)' 入力しなおしてください!'
GOTO 11
34 END IF
N=M
WRITE(6,*)'各列毎に、左辺の係数、右辺の数の順に入力して下さい'
DO 2 I=1,M
DO 1 J=1,M
W(J,J)=1.0
READ(5,*) A(I,J)
1 CONTINUE
READ(5,*) X(I)
2 CONTINUE
ELSE
12 CONTINUE
WRITE(6,*) ' DATA 数を入力して下さい'
READ(5,*,ERR=12) N
IF(N.LE.0) THEN
WRITE(6,*) ' 入力しなおしてください!'
GOTO 12
29 END IF
30 WRITE(6,*)' 最高次数決定の方法を選択して下さい'
WRITE(6,*)' 1:直接入力 2:自動決定'
READ(5,*,ERR=30) ICH
IF(ICH.LE.0.OR.ICH.GE.3) THEN
WRITE(6,*) ' 選択し直して下さい'
GOTO 30
31 END IF
IF(ICH.EQ.2) THEN
M=INT(2*SQRT(REAL(N)))
ELSE
9 WRITE(6,*) ' 求める最高次数を入力して下さい'
READ(5,*,ERR=9) M
IF(M.GE.N) THEN
WRITE(6,*)'次数を入力しなおして下さい'
GOTO 9
7 END IF
IF(MENU.EQ.4) THEN
M=M+1
END IF
END IF
WRITE(6,*)'DATA の入力方法を指定してください'
23 WRITE(6,*)'1:直接入力 2:DATA FILEによる入力'
READ(5,*,ERR=23) IDATA
IF(IDATA.LE.0.OR.IDATA.GE.3) GOTO 23
24 IF(IDATA.EQ.2) THEN
WRITE(6,*)'FILE の名前を入力してください'
READ(5,101) FILE
OPEN(1,FILE=FILE)
ELSE
WRITE(6,*)' X,Y の順に入力して下さい'
END IF
DO 5 J=1,N
W(J,J)=1.0
IF(IDATA.EQ.1) THEN
READ(5,*) XDATA,YDATA
ELSE
READ(1,*) XDATA,YDATA
END IF
IF(MENU.EQ.4) THEN
DO 3 I=1,M
A(J,I)=XDATA**(I-1)
3 CONTINUE
ELSE
DO 4 I=1,M
A(J,I)=XDATA**I
4 CONTINUE
END IF
X(J)=YDATA
5 CONTINUE
END IF
IF(IDATA.EQ.2) CLOSE(1)
RETURN
101 FORMAT(A25)
END
***********************************************************************
* SUBROUTINE TO EXECUTE QR-DIVISION *
***********************************************************************
SUBROUTINE QR(A,R,X,EN,NA,AM,MAX,ID)
C MODIFIED GRAM-SCHMIDT METHOD
INTEGER AM
DIMENSION A(MAX,MAX),R(MAX,MAX),EN(1)
INTEGER X(1)
DO 1 I=1,NA
X(I)=I
DO 1 J=1,AM
R(I,J)=0.0
1 CONTINUE
DO 2 J=1,AM
CALL NORM(A,EN,X,J,NA,AM,MAXNORM,MAX)
IF(J.NE.AM) THEN
ISTORE=X(J)
X(J)=MAXNORM
IX=X(MAXNORM)
X(IX)=ISTORE
IF(J.GE.2) THEN
IF(X(J).NE.X(IX)) THEN
DO 7 I=1,J-1
STORE=R(I,X(X(J)))
R(I,X(X(J)))=R(I,X(X(IX)))
R(I,X(X(IX)))=STORE
7 CONTINUE
END IF
END IF
END IF
R(J,J)=EN(X(J))
IF(R(J,J).LT.1.0E-6) THEN
WRITE(*,*)'ランク落ちがおこりました'
WRITE(*,*)'もう一度やり直してください'
ID=1
RETURN
END IF
DO 3 I=1,NA
A(I,X(J))=A(I,X(J))/R(J,J)
3 CONTINUE
DO 4 K=J+1,AM
DO 5 L=1,NA
R(J,K)=R(J,K)+A(L,X(J))*A(L,X(K))
5 CONTINUE
DO 6 L=1,NA
A(L,X(K))=A(L,X(K))-R(J,K)*A(L,X(J))
6 CONTINUE
4 CONTINUE
2 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO CALCULATE THE EUCLID NORM *
***********************************************************************
SUBROUTINE NORM(A,EN,X,IS,MA,NA,MAXNORM,MAX)
DIMENSION A(MAX,MAX),EN(1)
INTEGER X(1)
DO 1 JJ=IS,NA
J=X(JJ)
EN(J)=0.0
DO 2 I=1,MA
EN(J)=EN(J)+A(I,J)*A(I,J)
2 CONTINUE
EN(J)=SQRT(EN(J))
IF(JJ.EQ.IS) THEN
MAXNORM=J
ELSE
IF(EN(J).GT.EN(MAXNORM)) THEN
MAXNORM=J
END IF
END IF
1 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO MAKE TRANSPOSED-MATRIX *
***********************************************************************
SUBROUTINE TENMTX(A,B,M,N,MAX)
DIMENSION A(MAX,MAX),B(MAX,MAX)
DO 1 I=1,N
DO 2 J=1,M
B(I,J)=A(J,I)
2 CONTINUE
1 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO CALCCULATE THE PRODUCTION OF MATRIX A,B *
***********************************************************************
SUBROUTINE PRDMTX(A,B,C,L,M,N,MAX)
DIMENSION A(MAX,MAX),B(MAX,MAX),C(MAX,MAX)
DO 30 I=1,L
DO 20 J=1,N
C(I,J)=0.0
DO 10 K=1,M
C(I,J)=C(I,J)+A(I,K)*B(K,J)
10 CONTINUE
20 CONTINUE
30 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO TRANSLATE THE MATRIX *
***********************************************************************
SUBROUTINE TRANSMTX(A,B,X,M,N,MAX)
DIMENSION A(MAX,MAX),B(MAX,MAX)
INTEGER X(1)
DO 1 I=1,M
DO 2 J=1,N
B(I,J)=A(I,X(J))
2 CONTINUE
1 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO EXECUTE THE BACKWARD SUBSTITUTION *
***********************************************************************
SUBROUTINE BACK(R,A,Z,M,MAX)
DIMENSION R(MAX,MAX),A(1),Z(1)
DO 10 I=1,M
A(I)=0.0
10 CONTINUE
A(M)=Z(M)/R(M,M)
DO 1 I=M-1,1,-1
DO 2 J=I+1,M
A(I)=A(I)+R(I,J)*A(J)
2 CONTINUE
A(I)=(Z(I)-A(I))/R(I,I)
1 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO COPY MATRIX *
***********************************************************************
SUBROUTINE COPYMTX(A,B,M,N,MAX)
DIMENSION A(MAX,MAX),B(MAX,MAX)
DO 1 I=1,M
DO 2 J=1,N
B(I,J)=A(I,J)
2 CONTINUE
1 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO SOLVE THE MLS *
***********************************************************************
SUBROUTINE SOLVE(A,X,M,MENU)
DIMENSION A(1)
INTEGER X(1)
WRITE(*,203)
WRITE(*,*)
DO 10 LOOP=1,M
DO 20 J=1,M
IF(X(J).EQ.LOOP) THEN
I=J
GOTO 30
15 END IF
20 CONTINUE
30 CONTINUE
IF(MENU.EQ.1) THEN
WRITE(6,200) LOOP,A(I)
ELSE IF(MENU.EQ.3) THEN
WRITE(6,201) LOOP,A(I)
ELSE
WRITE(6,202) LOOP-1,A(I)
END IF
200 FORMAT(' X(',I3,') =',F13.3)
201 FORMAT(' ',I3,'次の係数 =',F13.6)
202 FORMAT(' ',I3,'次の係数 =',F13.6)
203 FORMAT( /,10X,'***** 結 果 の 出 力 *****')
10 CONTINUE
RETURN
END
***********************************************************************
* SUBROUTINE TO CALCULATE MENU 2 *
***********************************************************************
SUBROUTINE BEW(X,Y,W,SUM,Z,M)
DIMENSION X(1),Y(1),Z(1),W(1),SUM(1)
DO 1 I=1,M
W(I)=1.0
SUM(I)=W(I)
1 CONTINUE
DO 2 ICOUNT=1,10
XY=0.0
X2=0.0
DO 3 I=1,M
XY=XY+W(I)*X(I)*Y(I)
X2=X2+W(I)*X(I)*X(I)
3 CONTINUE
V2=0.0
A=XY/X2
WRITE(*,101) ICOUNT,A
DO 7 I=1,M
WRITE(6,102) I,W(I)
7 CONTINUE
DO 4 I=1,M
W(I)=ABS(Y(I)-A*X(I))
V2=V2+W(I)*W(I)
4 CONTINUE
CALL MEDIAN(W,M,Z,S)
C=20.8-15.0*EXP(-1.3730E-3*(S**1.5))
DO 5 I=1,M
IF(W(I).LT.S*C) THEN
W(I)=(1-(W(I)/(C*S))**2)**2
ELSE
W(I)=0.0
END IF
5 CONTINUE
HS=0.0
HB=0.0
DO 6 I=1,M
HS=HS+ABS(W(I)-SUM(I))
HB=HB+W(I)
SUM(I)=W(I)
6 CONTINUE
IF(HS.LT.HB*1.0E-4) RETURN
2 CONTINUE
RETURN
101 FORMAT(/,10X,I4,'回目の傾きの値 =',F13.6)
102 FORMAT(14X,I4,'番目の重み =',F13.6)
END
***********************************************************************
* SUBROUTINE TO SEARCH FOR THE MEDIAN *
***********************************************************************
SUBROUTINE MEDIAN(W,M,X,S)
DIMENSION W(1),X(1)
DO 1 I=1,M
X(I)=I
1 CONTINUE
ID=MOD(M,2)
IS=(M-ID)/2+1
DO 2 I=1,IS
DO 3 J=1,M-I
IF(W(X(J)).LT.W(X(J+1))) THEN
LARGE=X(J)
X(J)=X(J+1)
X(J+1)=LARGE
END IF
3 CONTINUE
2 CONTINUE
IF(ID.EQ.1) THEN
S=W(X(IS))
ELSE
S=(W(X(IS-1))+W(X(IS)))/2.0
END IF
RETURN
END
************************************************************************
* SUBROUTINE TO CALCULATE THE NUMBER OF AIC *
************************************************************************
SUBROUTINE AIC(V,XS,M,N,AI)
DIMENSION XS(1),V(1)
PAI=3.145927
SV=0.0
DO 1 I=1,N
V(I)=XS(I)-V(I)
SV=SV+V(I)*V(I)
1 CONTINUE
SV=SV/REAL(N)
IF(SV.EQ.0.0) THEN
WRITE(*,*)
WRITE(*,*) ' 残差0です!'
AI=-1.0E7
GOTO 5
2 END IF
AI=REAL(N)*(LOG(2*PAI*SV)+1.0)+2*(REAL(M)+1.0)
5 RETURN
END
************************************************************************
* SUBROUTINE TO TRANSLATE THE MATRIX ( SINGLE DIMENSION ) *
************************************************************************
SUBROUTINE TRANS(A,V,X,M)
DIMENSION A(1),V(1)
INTEGER X(1)
DO 1 LOOP=1,M
DO 20 J=1,M
IF(X(J).EQ.LOOP) THEN
I=J
GOTO 30
15 END IF
20 CONTINUE
30 V(LOOP)=A(I)
1 CONTINUE
RETURN
END
************************************************************************
* SUBROUTINE TO EXECUTE MENU 5 *
************************************************************************
SUBROUTINE MAKE2(X,Y,M,N,XDATA,JCH,MAX,MENU)
DIMENSION X(MAX,MAX),XDATA(MAX,MAX),Y(1)
INTEGER JCH(1)
CHARACTER FILE*25
1 WRITE(6,*) ' DATA 数を入力してください'
READ(5,*,ERR=1) N
IF(N.LE.0) GOTO 1
WRITE(6,*) ' パラメータ数を入力してください'
READ(5,*) M
IST=M
2 WRITE(6,*) ' DATA 入力の方法を入力してください'
3 WRITE(6,*) ' 1:直接入力 2:DATA FILE から入力'
READ(5,*,ERR=3) ICH
IF(ICH.LE.0.OR.ICH.GE.3) GOTO 3
4 IF(ICH.EQ.2) THEN
WRITE(6,*) ' FILE 名を入力してください'
READ(5,101) FILE
OPEN(1,FILE=FILE)
END IF
IF(MENU.EQ.5) THEN
JID=0
C IF(ICH.EQ.2) THEN
WRITE(6,*) '回帰するパラメータに1をしないものに0を'
WRITE(6,*) '入力して下さい'
DO 7 I=1,IST
6 WRITE(6,102) I
READ(5,*) JCH(I)
IF(JCH(I).NE.0.AND.JCH(I).NE.1) GOTO 6
IF(JCH(I).EQ.1) JID=JID+1
7 CONTINUE
M=JID+1
C ELSE
C DO 21 I=1,IST
C JCH(I)=1
C 21 CONTINUE
C END IF
DO 8 I=1,N
IF(ICH.EQ.2) THEN
READ(1,*) (XDATA(I,J),J=1,IST),Y(I)
ELSE
WRITE(6,*) 'X,Y の順に入力してください'
READ(5,*) (XDATA(I,J),J=1,IST),Y(I)
END IF
8 CONTINUE
IF(ICH.EQ.2) CLOSE(1)
DO 22 I=1,N
X(I,1)=1.0
22 CONTINUE
ICOUNT=1
DO 11 J=1,N
DO 10 I=2,M
9 CONTINUE
IF(JCH(ICOUNT).EQ.0) THEN
ICOUNT=ICOUNT+1
GOTO 9
END IF
X(J,I)=XDATA(J,ICOUNT)
ICOUNT=ICOUNT+1
10 CONTINUE
ICOUNT=1
11 CONTINUE
END IF
RETURN
101 FORMAT(A25)
102 FORMAT(' X(',I3,')')
END
************************************************************************
* SUBROUTINE TO CALUCULATE THE NUMBER OF AIC AT MENU 5 *
************************************************************************
SUBROUTINE AIC5(X,Y,A,JCH,M,N,MAX,AI)
DIMENSION X(MAX,MAX),Y(1),A(1)
INTEGER JCH(1)
PAI=3.141593
SIGONE=0.0
SIGTWO=0.0
SIGTHR=0.0
DO 1 I=1,N
SIGONE=SIGONE+Y(I)**2
SIGTWO=SIGTWO+Y(I)
1 CONTINUE
SIGTWO=A(1)*SIGTWO
ICOUNT=1
DO 3 J=2,M
DO 2 I=1,N
10 IF(JCH(ICOUNT).EQ.0) THEN
ICOUNT=ICOUNT+1
GOTO 10
11 END IF
SIGTHR=SIGTHR+X(I,ICOUNT)*Y(I)*A(J)
2 CONTINUE
ICOUNT=ICOUNT+1
3 CONTINUE
SIGMA=(SIGONE-SIGTWO-SIGTHR)/REAL(N)
AI=N*(LOG(2*PAI)+1)+N*LOG(SIGMA)+2*(M+1)
WRITE(6,100) AI
RETURN
100 FORMAT( /,' A I C =',F13.6)
END